package com.neusoft.yiyang.auth.service.impl;

import com.neusoft.yiyang.auth.client.UserClient;
import com.neusoft.yiyang.auth.security.JwtTokenProvider;
import com.neusoft.yiyang.auth.service.AuthService;
import com.neusoft.yiyang.auth.service.CaptchaService;
import com.neusoft.yiyang.common.entity.user.User;
import com.neusoft.yiyang.common.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    @Autowired
    private UserClient userClient;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private CaptchaService captchaService;

    @Override
    public Map<String, String> login(String username, String password, String captchaKey, String inputCaptcha) {
        // 1. 验证验证码
        String storedCaptcha = redisTemplate.opsForValue().get("captcha:" + captchaKey);
        if (storedCaptcha == null) {
            throw new BusinessException(3001, "验证码已过期，请重新获取");
        }
        
        if (!captchaService.validateCaptcha(inputCaptcha, storedCaptcha)) {
            throw new BusinessException(3002, "验证码错误");
        }
        
        // 验证通过后删除验证码，防止重复使用
        redisTemplate.delete("captcha:" + captchaKey);
        
        // 2. 验证用户和密码
        User user = userClient.getUserByUsername(username);
        if (user == null) {
            throw new BusinessException(3003, "用户不存在");
        }
        
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new BusinessException(3004, "密码错误");
        }
        
        // 3. 生成Token
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getUserId());
        claims.put("username", user.getUsername());
        claims.put("roleId", user.getRoleId());

        String accessToken = jwtTokenProvider.generateToken(
                claims,
                String.valueOf(user.getUserId())
        );
        String refreshToken = UUID.randomUUID().toString().replace("-", "");
        
        // 4. 存储RefreshToken到Redis
        redisTemplate.opsForValue().set(
            "jwt:refresh:" + refreshToken, 
            user.getUsername(), 
            7, 
            TimeUnit.DAYS
        );

        // 5. 返回结果
        Map<String, String> tokens = new HashMap<>();
        tokens.put("accessToken", accessToken);
        tokens.put("refreshToken", refreshToken);
        return tokens;
    }

    @Override
    public Map<String, String> refreshToken(String refreshToken) {
        // 1. 检查RefreshToken是否存在
        String username = redisTemplate.opsForValue().get("jwt:refresh:" + refreshToken);
        if (username == null) {
            throw new BusinessException(3005, "刷新令牌无效或已过期");
        }
        
        // 2. 删除旧的RefreshToken
        redisTemplate.delete("jwt:refresh:" + refreshToken);
        
        // 3. 获取用户信息
        User user = userClient.getUserByUsername(username);
        if (user == null) {
            // 用户可能已被删除
            throw new BusinessException(3003, "用户不存在");
        }
        
        // 4. 生成新的Token
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getUserId());
        claims.put("username", user.getUsername());
        claims.put("roleId", user.getRoleId());

        String newAccessToken = jwtTokenProvider.generateToken(
                claims,
                String.valueOf(user.getUserId())
        );
        String newRefreshToken = UUID.randomUUID().toString().replace("-", "");
        
        // 5. 存储新的RefreshToken
        redisTemplate.opsForValue().set(
            "jwt:refresh:" + newRefreshToken, 
            username, 
            7, 
            TimeUnit.DAYS
        );
        
        // 6. 返回新的双令牌
        Map<String, String> tokens = new HashMap<>();
        tokens.put("accessToken", newAccessToken);
        tokens.put("refreshToken", newRefreshToken);
        return tokens;
    }

    @Override
    public void logout(String token) {
        // 1. 验证Token是否有效
        if (!jwtTokenProvider.validateToken(token)) {
            return;
        }
        
        // 2. 获取Token剩余有效期
        long remainingTime = jwtTokenProvider.getTokenRemainingTime(token);
        
        // 3. 将Token加入黑名单，设置过期时间为剩余有效期
        if (remainingTime > 0) {
            redisTemplate.opsForValue().set(
                "jwt:blacklist:" + token, 
                "1", 
                remainingTime, 
                TimeUnit.MILLISECONDS
            );
        }
    }
}